/*  This program is free software; you can redistribute it and/or modify it
    under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 2.1 of the License, or (at
    your option) any later version.
    For more details, see the GNU Lesser General Public License (www.fsf.org
    or the COPYING file somewhere in the package)
 */

#include "ConfigFile.hh"

/*! @file src/OSGi/ConfigFile.cc
    @brief Class OSGi::ConfigFile (non-inline) methods.
    @author @ref Guillaume_Terrissol
    @date 17th December 2009 - 22nd January 2014
    @note This file is distributed under the LGPL license.
    Refer to the file COPYING (or http://www.fsf.org) for more information.
 */

#include <fstream>
#include <stdexcept>

#if !defined(SI_SUPPORT_IOSTREAMS)
#   define   SI_SUPPORT_IOSTREAMS
#endif  //   SI_SUPPORT_IOSTREAMS

#include "Properties.hh"
#include "SimpleIni.h"

namespace OSGi
{
    /*! @param pFilename Configuration filename
     */
    ConfigFile::ConfigFile(std::string pFilename)
        : mFilename{pFilename}
    { }


    /*! @param pProps Properties to fill with data found in file
        @warning Properties found outside any section will be assign the
                 "Unknown" section
        @warning Properties already present in @p pProps won't be overwritten
     */
    void ConfigFile::update(Properties& pProps)
    {
        update(pProps, "Unknown");
    }


    /*! @param pProps          Properties to fill with data found in file
        @param pDefaultSection Section to assign to keys found outside section
        @warning Properties already present in @p pProps won't be overwritten
     */
    void ConfigFile::update(Properties& pProps, std::string pDefaultSection)
    {
        CSimpleIniCase  lIni{true, false, false};
        std::ifstream   lFile{mFilename.c_str(), std::fstream::in | std::fstream::binary};

        if (0 <= lIni.Load(lFile))
        {
            CSimpleIniCase::TNamesDepend    lSections{};
            lIni.GetAllSections(lSections);
            
            for(const auto& s : lSections)
            {
                CSimpleIniCase::TNamesDepend    lKeys{};
                if (lIni.GetAllKeys(s.pItem, lKeys))
                {
                    for(const auto& k : lKeys)
                    {
                        std::string lValue{lIni.GetValue(s.pItem, k.pItem)};
                        if ((s.pItem != 0) && (strlen(s.pItem) != 0))
                        {
                            auto    lKey = std::string{s.pItem} + "." + std::string{k.pItem};
                            if (!pProps.has(lKey))
                            {
                                pProps.set(lKey, lValue);
                            }
                        }
                        else
                        {
                            auto    lKey = std::string{k.pItem};
                            if (!pDefaultSection.empty())
                            {
                                lKey = pDefaultSection + "." + lKey;
                            }
                            if (!pProps.has(lKey))
                            {
                                pProps.set(lKey, lValue);
                            }
                        }
                    }
                }
            }
        }
        else
        {
            throw std::invalid_argument{"Invalid config file : " + mFilename};
        }
    }
}
